#include "River.h"

void River::Generate(Terrain* t)
{
	m_vPos=t->GetPos()-D3DXVECTOR3(t->GetAbsSize()/2,0,t->GetAbsSize()/2);
	Fractal* fractal = t->GetFractal();
	Graph* graph = &t->GetFractal()->GetGraph();

	int Tsize=t->GetNumCells();
	int numNodes = graph->GetNumNodes();
	int curNode=-1;
	D3DXVECTOR3 source,pos,nextPos;
	float CurHighest = -10000000;
	int cellSize = t->GetCellSize();
	for(unsigned int i=0; i<numNodes;++i)
	{
		D3DXVECTOR2 nodePos = graph->GetNode(i)->GetPos();
		int height = fractal->GetPoint(nodePos);
		pos = D3DXVECTOR3(nodePos.x,height,nodePos.y);

		if((pos.x == 0) || (pos.z == 0) || (pos.x == Tsize) || (pos.z ==Tsize)) //is on the edge
		{
			if(pos.y>CurHighest)
			{
				CurHighest=pos.y;
				source=pos;
				curNode=i;
			}
		}

	}

	m_pvPath.push_back(source);

	std::vector<int> visitedNodes;
	visitedNodes.push_back(curNode);
	int length =0;
	while((length<100)&&(nextPos.x != 0) && (nextPos.z != 0) && (nextPos.x != Tsize) && (nextPos.z != Tsize) || (length<Tsize/2))
	{

		std::list<GraphEdge> gl = graph->GetEdgeList(curNode);
		float lowestCost = 100000;
		GraphNode* nextNode;

		for (std::list<GraphEdge>::iterator it = gl.begin();it!=gl.end();++it)
		{
			int dest = (*it).GetTo();
			bool skip =false;
			for(unsigned int i=0;i<visitedNodes.size();++i)
			{
				if(visitedNodes[i]==dest)
				{
					skip=true;
				}
			}
			float cost = (*it).GetCost();

			if(cost<lowestCost && !skip)
			{
				lowestCost=cost;
				nextNode = graph->GetNode(dest);
				nextPos = D3DXVECTOR3(nextNode->GetPos().x,fractal->GetPoint(nextNode->GetIndex()),nextNode->GetPos().y);
			}

		}
		m_pvPath.push_back(nextPos);
		visitedNodes.push_back(curNode);
		curNode=nextNode->GetIndex();
		length++;
	}

	m_pvPath.push_back(nextPos);
	HRESULT hr;
	const int height=32;
	const int width=32;
	m_RiverTex=new Texture;

	V( D3DXCreateTexture(TheD3DApp::Instance()->GetD3DDev(),width,height,D3DX_DEFAULT,D3DUSAGE_DYNAMIC,
		D3DFMT_X8R8G8B8,D3DPOOL_DEFAULT,&m_RiverTex->m_pTex));

	D3DCOLORVALUE color[height*width];
	for (int i=0;i<width*height;++i)
	{
		color[i].r=1.0f;
		color[i].g=0.1f;
		color[i].b=0.1f;
		color[i].a=1.0f;
	}
	D3DXFillTexture(m_RiverTex->m_pTex,CF,color);

	LPD3DXMESH meshes[100];
	for (unsigned int i=0;i<m_pvPath.size()-1;++i)
	{
		D3DXVECTOR3 start =m_pvPath[i]+D3DXVECTOR3(0,0.1,0);
		D3DXVECTOR3 end = m_pvPath[i+1]+D3DXVECTOR3(0,0.1,0);
		start.x *=cellSize;
		start.z *=cellSize;
		end.x *=cellSize;
		end.z *=cellSize;
		D3DXVECTOR3 straight = end-start;
		D3DXVECTOR3 right(straight.z,straight.y,straight.x);
		D3DXVec3Normalize(&right,&right);
		//right*=cellSize;
		V(D3DXCreateMesh(2,4,D3DXMESH_MANAGED,TheD3DApp::Instance()->GetVertexElements(),TheD3DApp::Instance()->GetD3DDev(),&meshes[i]));

		int vertCount=0;
		POSNORMUVVERTEX* pVertices;
		V(meshes[i]->LockVertexBuffer(0,(void**)&pVertices));
		pVertices[vertCount].Pos= start-right;
		pVertices[vertCount].Norm=D3DXVECTOR3(0,1,0);
		pVertices[vertCount].UV=D3DXVECTOR2(0,0);
		vertCount++;

		pVertices[vertCount].Pos= start+right;
		pVertices[vertCount].Norm=D3DXVECTOR3(0,1,0);
		pVertices[vertCount].UV=D3DXVECTOR2(1,0);
		vertCount++;

		pVertices[vertCount].Pos= end-right;
		pVertices[vertCount].Norm=D3DXVECTOR3(0,1,0);
		pVertices[vertCount].UV=D3DXVECTOR2(0,1);
		vertCount++;

		pVertices[vertCount].Pos= end+right;
		pVertices[vertCount].Norm=D3DXVECTOR3(0,1,0);
		pVertices[vertCount].UV=D3DXVECTOR2(1,1);
		vertCount++;

		V(meshes[i]->UnlockVertexBuffer());
		int indCount=0;
		WORD *IndexData=NULL;
		V(meshes[i]->LockIndexBuffer(0,(void**)&IndexData));


		IndexData[indCount++]=0;
		IndexData[indCount++]=1;
		IndexData[indCount++]=2;

		IndexData[indCount++]=2;
		IndexData[indCount++]=1;
		IndexData[indCount++]=3;


		V(meshes[i]->UnlockIndexBuffer());
		AddTexture(m_RiverTex);
	}

	V(D3DXConcatenateMeshes(meshes,m_pvPath.size()-2,D3DXMESH_MANAGED,0,0,TheD3DApp::Instance()->GetVertexElements(),TheD3DApp::Instance()->GetD3DDev(),&m_pMesh));
	V(m_pMesh->OptimizeInplace(D3DXMESHOPT_COMPACT ,0,0,0,0));
	V(D3DXComputeNormals(m_pMesh,0));
}